package com.dc.commons.json;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

import com.dc.commons.json.format.DateFormat;
import com.dc.commons.json.format.DateTimeFormat;
import com.dc.commons.json.format.TimeFormat;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonFormat.Value;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
import com.fasterxml.jackson.databind.module.SimpleModule;

/*******************************************************************************<P>
 * 文件名: DcObjectMapper.java <br>
 * 版本: 1.0<br>
 * 描述:Json ObjectMapper 扩展类 ，设置了运行单引号，字段不带引号，忽略不存在的字段，<br>
 * 		默认的时区，时间格式，异常处理<br>
 * 版权所有: <br>
 * <P>
 * 创建者: 王建栋 <br>
 * 创建日期: 2015年12月16日 上午10:05:34<br>
 * 修改者: <br>
 * 修改日期: <br>
 * 修改说明: <br>
 *****************************************************************************
 */
public class DcObjectMapper extends ObjectMapper{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public DcObjectMapper(){
		//允许单引号
		this.configure(Feature.ALLOW_SINGLE_QUOTES, true);
		//允许字段不带引号
		this.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
		//忽略不存在的字段
		this.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
		 // 空值处理为空串
		this.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>(){
			@Override
			public void serialize(Object value, JsonGenerator jgen,
					SerializerProvider provider) throws IOException,
					JsonProcessingException {
				jgen.writeString("");
			}
        });
		
		/**
		 * 对异常 进行转码
		 */
		this.registerModule(new SimpleModule().addSerializer(Exception.class,new JsonSerializer<Exception>(){

			@Override
			public void serialize(Exception value, JsonGenerator gen, SerializerProvider serializers)
					throws IOException, JsonProcessingException {
				ByteArrayOutputStream out=new ByteArrayOutputStream();
				PrintStream printStream=new PrintStream(out);
				value.printStackTrace(printStream);
				gen.writeString(value.getMessage()+" cause "+new String(out.toByteArray()));
			}
			
		}));
		/**
		 *  进行HTML解码。
		 */
		this.registerModule(new SimpleModule().addSerializer(String.class, new JsonSerializer<String>(){
			@Override
			public void serialize(String value, JsonGenerator jgen,
					SerializerProvider provider) throws IOException,
					JsonProcessingException {
				// TODO 需要实现HTML 解码
				jgen.writeString(value);
			}
        }));
		
		
		/**
		 * 重写 Json格式化
		 */
		this.setAnnotationIntrospector(new JacksonAnnotationIntrospector(){
			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			@Override
			public Value findFormat(Annotated ann) {
				DateTimeFormat dateTimeFormat = _findAnnotation(ann, DateTimeFormat.class);
				if(dateTimeFormat!=null){
					return new JsonFormat.Value(dateTimeFormat.annotationType().getAnnotation(JsonFormat.class));
				}else{
					DateFormat dateFormat = _findAnnotation(ann, DateFormat.class);
					if(dateFormat!=null){
						return new JsonFormat.Value(dateFormat.annotationType().getAnnotation(JsonFormat.class));
					}else{
						TimeFormat timeFormat = _findAnnotation(ann, TimeFormat.class);
						if(timeFormat!=null){
							return new JsonFormat.Value(timeFormat.annotationType().getAnnotation(JsonFormat.class));
						}
					}
				}
				return super.findFormat(ann);
			}
			
		});
		
		
		/**
		 * 默认的时间格式
		 */
		this.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
		
		/**
		 *  设置时区
		 */
		this.setTimeZone(TimeZone.getDefault());//getTimeZone("GMT+8:00")
		
		
	} 
	
	
}
